import { RouteConfig } from '@jsjn/types/Route'
import _ from 'lodash'
import store from '@jsjn/micro-core-store'

/**
 * 具体的微应用在引用当前模块时，会解析 @ 符号
 * 每个微应用的 vue.config.js 里都将 @ 别名配置为本地文件夹
 * 所以，这里直接使用 @/ 可以定位到自己的文件夹下
 * 相当于自适应匹配
 */
const files = require.context('@/router/modules', false, /\.ts$/)

const systemRouteConfigTree = _.cloneDeep(
    files.keys().reduce((routes, path) => {
        const module = files(path).default

        /**
         * 子应用在路由注册时分为两种情况
         * 1. 单独应用（无__MICRO_APP_BASE_ROUTE__），应注册为 根 / 路由
         * 2. 作为子应用运行在基座中，应拼接基座传递的 __MICRO_APP_BASE_ROUTE__ 的根路由
         */
        const rootRoutesModule = module.map((item) => ({
            ...item,
            path: `${window['__MICRO_APP_BASE_ROUTE__']}/${item.path}`
        }))

        routes = routes.concat(rootRoutesModule)
        return routes
    }, [])
)

/**
 * 多维数组变为一维数组注册路由
 * 实际上，业务模块的路由都应期望放在 Main 组件下，但是路由的声明文件最好拥有层级结构（并适用菜单的配置）
 * 故：将声明的路由配置 “拉平” 成一维数组，集中注册到 '/' 路由下，使其能够在 Main 组件下的 <router-view /> 展示
 */
export function routeConfigs2RegisteredRoutes(source: Array<RouteConfig>): RouteConfig[] {
    for (let i = 0; i < source.length; i++) {
        if (source[i].children) {
            const parentPath = source[i].path

            // 子拼接父 的路径标识
            source[i].children!.forEach((subItem) => {
                subItem.path = `${parentPath}/${subItem.path}`

                /**
                 * 静态路由同步动态路由的设置
                 * 避免出现歧义
                 * 如果页面标识模糊匹配，需要添加 /:page* 的 params
                 */
                if (subItem.meta.isBlurry) {
                    subItem.path = `${subItem.path}/:page*`
                }
            })

            // 父拼接子 行成一维数组
            source = source.slice(0, i + 1).concat(source[i].children!, source.slice(i + 1))
        }
    }

    // 当前方法是基于引用改变的数据，所以在方法处理完后，源数据的节点也被改变
    store.commit('appFuncTree/setRouteConfigs', _.cloneDeep(systemRouteConfigTree))
    return source.filter((route) => route.component || route.path === '/')
}

/**
 * 子应用的前端路由注册不需要提供给菜单使用，个别系统除外，已知：
 *  - c 端用户中心
 */
export let frontEndRoutes: RouteConfig[] = null
export default (): RouteConfig[] => {
    if (frontEndRoutes) return frontEndRoutes
    frontEndRoutes = routeConfigs2RegisteredRoutes(systemRouteConfigTree)
    return frontEndRoutes
}
